iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 16
0
Modern Web

30天入門JavaScript系列 第 16

【Day 16】提升Hoisting

  • 分享至 

  • xImage
  •  



不管是JavaScript還是其他程式語言,通常都是逐行執行的,
在之前的例子中,都會先宣告好變數跟函式再使用。


像這樣

function say() {
    console.log('hello world');
  }
var num = 2;

console.log(num);//2
say(); //印出hello world


畢竟沒有宣告的話,執行時會跳出錯誤,以正常人的邏輯都是建立好一個值後才能使用。


那如果反過來,先使用才宣告呢?

console.log(num);//undefined
say();//印出hello world

function say() {
  console.log('hello world');
}
var num = 2;


此時不會跳錯誤,函式能正常執行,但變數印出的結果變成undefined,代表函式跟變數有被宣告,但變數沒有被賦值。

有人會說其實是JavaScript幫你把程式碼處理過了,
處理過的程式碼長這樣:

function say() {
    console.log('hello world');
  }
var num;

console.log(num);//因為還沒有賦值 所以印出undefined
say();//印出hello world
num = 2;

JavaScript幫你把宣告拉到程式的最上面,所以這種情況叫做提升(Hoisting)






https://ithelp.ithome.com.tw/upload/images/20200916/20129836v256AB0ljN.jpg

執行結果一樣,但不代表真的是這樣運作,
如果JavaScript真的亂移動程式碼大概會被罵死(

實際上會造成這種情況的原因,是JavaScript在建立新執行環境時的處理,建立新執行環境時,JavaScript先確定好環境內可以使用的變數跟函式,為其配置記憶體空間

一樣用這個程式當作範例

console.log(num);
say();

function say() {
  console.log('hello world');
}
var num = 2;



JavaScript對這程式的處理程序是:

  1. 開始建立全域環境,尋找環境內會用到的變數跟函式
  2. 找到會用到的函式say(),在記憶體配置
  3. 找到變數num,在記憶體配置變數num,但還沒有值
  4. 執行程式碼,印出num的值(undefined)
  5. 執行say(),建立區域環境,不過環境內沒有變數跟函式
  6. 執行程式碼,印出hello world,執行結束區域環境消滅
  7. 回到全域環境,賦值給num

拉升的應用

所以拉升可以讓我們把函式宣告在喜歡的位置,讓程式碼更好理解
像如果想實作一個把陣列依照英文字母排序的函式

function sortArrayByName(arr) {
  return arr.sort(function (a, b) {
    for (let i = 0; i < Math.min(a.length, b.length); i++) {
      if (a[i] > b[i]) {
        return 1;
      } else if (a[i] < b[i]) {
        return -1;
      }
    }
    return a.length > b.length ? 1 : -1;
  });
}


直接在引數的位置寫排序用的函式會很難閱讀,
把排序用函式宣告在上方的話會好讀一點,但還是讀到最後一行才知道這個函式在做甚麼。

但如果利用提升

function sortArrayByName(arr) {
  return arr.sort(sortByName);
//------------------------------
  function sortByName(a, b) {
    for (let i = 0; i < Math.min(a.length, b.length); i++) {
      if (a[i] > b[i]) {
        return 1;
      } else if (a[i] < b[i]) {
        return -1;
      }
    }
    return a.length > b.length ? 1 : -1;
  }
}


用這方式只要看第一行就知道sortArrayByName這函式會回傳甚麼,
想看排序的方式詳細才需要看下半部。


上一篇
【Day 15】執行環境與呼叫堆疊
下一篇
【Day 17】範圍 scope
系列文
30天入門JavaScript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言